using System;
using System.IO;
using CodePlex.TfsLibrary;
using CodePlex.TfsLibrary.ClientEngine;
using CodePlex.TfsLibrary.ObjectModel;

namespace CodePlex.CodePlexClientLibrary
{
    public class StatusConsoleView : IStatusView
    {
        string baseDirectory;
        readonly bool connectToServer;
        readonly string localPath;
        readonly StatusViewPresenter presenter;
        readonly bool verbose;

        public StatusConsoleView(ITfsEngine engine,
                                 string localPath,
                                 bool verbose,
                                 bool recursive,
                                 bool connectToServer)
        {
            this.localPath = localPath;
            this.verbose = verbose;
            this.connectToServer = connectToServer;

            presenter = new StatusViewPresenter(this, engine, verbose, recursive, connectToServer);
        }

        public void DisplayError(string path,
                                 SourceItemResult result)
        {
            ConsoleUtil.PrintCommandError(path, result);
        }

        public void DisplayItem(SourceItem item)
        {
            string clientStatus = GetClientStatusText(item);
            string clientChangeset = GetClientChangesetIdText(item);
            string serverStatus = GetServerStatusText(item);
            string serverChangeset = GetServerChangesetIdText(item);

            if (verbose || clientStatus != "" || serverStatus != "")
            {
                string relativePath = CodePlexClientUtil.GetRelativePath(baseDirectory, item.LocalName);
                Console.WriteLine("{0,1} {1,1}  {2}{3}{4}", clientStatus, serverStatus, clientChangeset, serverChangeset, relativePath);
            }
        }

        public void DisplayNoItemsMessage()
        {
            Console.WriteLine("No items to show.");
        }

        static string FormatChangesetId(int changesetId)
        {
            string id = "";

            if (changesetId != Constants.NullChangesetId)
                id = changesetId.ToString();

            return string.Format("{0,9}  ", id);
        }

        string GetClientChangesetIdText(SourceItem item)
        {
            if (verbose)
                return FormatChangesetId(item.LocalChangesetId);

            return "";
        }

        static string GetClientStatusText(SourceItem item)
        {
            if (item.LocalName == null)
                return "";

            switch (item.LocalItemStatus)
            {
                case SourceItemStatus.Add:
                    return "A";
                case SourceItemStatus.Conflict:
                    return "C";
                case SourceItemStatus.Delete:
                    return "D";
                case SourceItemStatus.Missing:
                    return "!";
                case SourceItemStatus.Modified:
                    return "M";
                case SourceItemStatus.Unmodified:
                    return "";
                case SourceItemStatus.Unversioned:
                    return "?";
                default:
                    throw new ArgumentOutOfRangeException("item", item.LocalItemStatus,
                                                          "Unexpected local status value: " + item.LocalItemStatus);
            }
        }

        string GetServerChangesetIdText(SourceItem item)
        {
            if (verbose && connectToServer)
                return FormatChangesetId(item.RemoteChangesetId);

            return "";
        }

        static string GetServerStatusText(SourceItem item)
        {
            if (item.RemoteName == null)
                return "";

            switch (item.RemoteItemStatus)
            {
                case SourceItemStatus.Add:
                    return "+";
                case SourceItemStatus.Delete:
                    return "-";
                case SourceItemStatus.Modified:
                    return "*";
                case SourceItemStatus.Unmodified:
                    return "";
                default:
                    throw new ArgumentOutOfRangeException("item", item.RemoteItemStatus,
                                                          "Unexpected remote status value: " + item.RemoteItemStatus);
            }
        }

        public bool QueryForResolve(string filename)
        {
            throw new NotImplementedException();
        }

        public void RemoveItem(string path) {}

        public void Run()
        {
            if (Directory.Exists(localPath))
                baseDirectory = localPath;
            else
                baseDirectory = Path.GetDirectoryName(localPath);

            presenter.Run(localPath);
        }

        public bool ShowView()
        {
            return false;
        }
    }
}